﻿using ComLib.ComType;
using DeviceCommon;
using LogLib;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace CVR100AReader
{
    public class CVRReaderOld : DeviceBase
    {
        /// <summary>
        /// 阅读器连接的串口号（或者USB接口索引）
        /// </summary>
        protected int _iPort = 0;
        public int iPort
        {
            get { return _iPort; }
        }

        private bool isReading = false;

        private Polling poll = null;

        protected readonly string strZPPath = @"D:\\zp.bmp";

        /// <summary>
        /// 阅读器选项
        /// </summary>
        protected IDCReaderOption _option = new IDCReaderOption();
        public IDCReaderOption Option
        {
            get { return _option; }
            set { _option = value; }
        }

        public CVRReaderOld()
        {
            LoadConfig();
        }

        public bool CloseCVRReader()
        {
            int num = TermbDll_100A.CVR_CloseComm();
            Log.WriteAsync(string.Format("关闭身份证阅读器{0}", (num == 1) ? "成功" : "失败"));
            if(num == 1)
            {
                _bInited = false;
                _bExited = true;
                _state = DeviceState.NotInitialized;
                return true;
            }
            else
            {
                return false;
            }
        }

        public bool ReadCard(out IdCardInfo sender)
        {
            sender = null;
            if (isReading)
            {
                return false;
            }              
            isReading = true;         
            DateTime now = DateTime.Now;           
            int num = 0;
            try
            {
                int count = 0;
                while(TermbDll_100A.CVR_Authenticate() != 1 && count < 10)
                {
                    count++;
                    Thread.Sleep(300);
                }
                num = TermbDll_100A.CVR_Authenticate();
                if (count >= 10 && num != 1)
                {
                    _error = $"寻卡失败, code:{num}";
                    Log.WriteAsync(_error);
                    return false;
                }
                if (num != 1)
                {
                   _error = string.Format("调用CVR_Authenticate返回值{0}，认证失败", num);
                   Log.WriteAsync(_error);
                    return false;
                }
                Log.WriteAsync("调用CVR_Authenticate，认证成功");
                num = TermbDll_100A.CVR_Read_Content(4);
                if (num != 1)
                {
                    _error = $"调用CVR_Read_Content返回值{num}，读身份证失败";
                    Log.WriteAsync(_error);
                    return false;
                }
                Log.WriteAsync("获取身份证详细信息");
                int strLen = 30;
                byte[] bName = new byte[strLen];
                TermbDll_100A.GetPeopleName(ref bName[0], ref strLen);
                strLen = 0x24;
                byte[] bIdNum = new byte[strLen];
                TermbDll_100A.GetPeopleIDCode(ref bIdNum[0], ref strLen);
                string sfzh = System.Text.Encoding.ASCII.GetString(bIdNum);
                //MessageBox.Show(sfzh);
                strLen = 30;
                byte[] bNational = new byte[strLen];
                TermbDll_100A.GetPeopleNation(ref bNational[0], ref strLen);
                strLen = 0x10;
                byte[] bStratDate = new byte[strLen];
                TermbDll_100A.GetStartDate(ref bStratDate[0], ref strLen);
                strLen = 0x10;
                byte[] bBirthday = new byte[strLen];
                TermbDll_100A.GetPeopleBirthday(ref bBirthday[0], ref strLen);
                strLen = 70;
                byte[] bAddress = new byte[strLen];
                TermbDll_100A.GetPeopleAddress(ref bAddress[0], ref strLen);
                strLen = 0x10;
                byte[] bEndDate = new byte[strLen];
                TermbDll_100A.GetEndDate(ref bEndDate[0], ref strLen);
                strLen = 30;
                byte[] bDepartment = new byte[strLen];
                TermbDll_100A.GetDepartment(ref bDepartment[0], ref strLen);
                strLen = 30;
                byte[] bSex = new byte[strLen];
                TermbDll_100A.GetPeopleSex(ref bSex[0], ref strLen);
                strLen = 0x400;
                byte[] bFinger = new byte[strLen];
                TermbDll_100A.GetFPDate(ref bFinger[0], ref strLen);
                StringBuilder builder = new StringBuilder();
                int index = 0;
                while (true)
                {
                    if (index < 0x400)
                    {
                        builder.Append(string.Format("{0:X2}", bFinger[index]));
                        index++;
                        continue;
                    }
                    Encoding unicode = Encoding.Default;
                    string str2 = unicode.GetString(bIdNum).Replace("\0", "").Trim();
                    string dateTime = unicode.GetString(bStratDate).Replace("\0", "").Trim();
                    string time = unicode.GetString(bEndDate).Replace("\0", "").Trim();
                    if (string.IsNullOrEmpty(str2) || ((str2.Length != 0x12) && (str2.Length != 15)))
                    {
                        Log.WriteAsync(string.Format("身份证号有误，身份证号:{0},长度:{1}", str2, str2.Length));
                    }
                    else
                    {
                        sender = new IdCardInfo
                        {
                            Fingerdata = builder.ToString(),
                            IdCardCode = str2,
                            IdCardName = unicode.GetString(bName).Replace("\0", "").Trim(),
                            Address = unicode.GetString(bAddress).Replace("\0", "").Trim(),
                            Sex = unicode.GetString(bSex).Replace("\0", "").Trim(),
                            Birthday = unicode.GetString(bBirthday).Replace("\0", "").Trim()
                        };
                        sender.Birthday = this.GetTime(sender.Birthday, "yyyy-MM-dd");
                        sender.Department = unicode.GetString(bDepartment).Replace("\0", "").Trim();
                        sender.Nation = unicode.GetString(bNational).Replace("\0", "").Trim();
                        dateTime = this.GetTime(dateTime, "yyyy.MM.dd");
                        time = this.GetTime(time, "yyyy.MM.dd");
                        sender.IssueDate = dateTime;
                        sender.ExpiryDate = time;
                        if (!string.IsNullOrEmpty(dateTime) && !string.IsNullOrEmpty(time))
                        {
                            sender.Validate = dateTime + "-" + time;
                        }
                        else
                        {
                            _error = "有效期限出现乱码";
                            Log.WriteAsync("有效期限出现乱码");
                            sender.Validate = "未知";
                        }
                        string path = System.Environment.GetEnvironmentVariable("TMP") + "\\chinaidcard\\xp.bmp";
                        sender.Photo = path; /*File.ReadAllBytes(path);*/
                        Log.WriteAsync(string.Format("姓名:{0},性别:{1},出生日期{2},签发机关:{3},身份证号:{4},民族:{5},起始日期:{6},有效期限:{7}, 头像路径:{8}", 
                            new object[] {
                                sender.IdCardName, 
                                sender.Sex, 
                                sender.Birthday, 
                                sender.Department, 
                                sender.IdCardCode, 
                                sender.Nation, 
                                dateTime, 
                                time,
                                path
                            }));                       
                    }
                    break;
                }
                return true;
            }
            catch (Exception exception)
            {
                sender = null;
                _error = "读身份证异常GetReadIDCard Error:" + exception.ToString();
                Log.WriteAsync(_error);
                return false;
            }
            finally
            {
                isReading = false;
            }           
        }

        private string GetTime(string dateTime, string format)
        {
            try
            {
                string s = dateTime;
                if (dateTime.Length == 8)
                {
                    string[] strArray = new string[] { dateTime.Substring(0, 4), "-", dateTime.Substring(4, 2), "-", dateTime.Substring(6, 2) };
                    s = string.Concat(strArray);
                }
                return DateTime.Parse(s).ToString(format);
            }
            catch (Exception)
            {
                return "";
            }
        }

        public bool InitCVRReader()
        {
            try
            {
                int num = 0;
                int port = 0;
                port = 0x3e9;
                while (true)
                {
                    bool flag2 = port <= 0x3f8;
                    if (flag2)
                    {
                        num = TermbDll_100A.CVR_InitComm(port);
                        if (num != 1)
                        {
                            port++;
                            continue;
                        }
                        _iPort = port;
                        Log.WriteAsync(string.Format("身份证阅读器初始化成功，USB口{0}", port));
                        return true;
                    }
                    else
                    {
                        port = 1;
                        while (true)
                        {
                            flag2 = port <= 0x10;
                            if (!flag2)
                            {
                                break;
                            }
                            num = TermbDll_100A.CVR_InitComm(port);
                            if (num != 1)
                            {
                                port++;
                                continue;
                            }
                            _iPort = port;
                            SavePort();
                            Log.WriteAsync(string.Format("打开身份证阅读器成功，串口{0}", port));
                            return true;
                        }
                    }
                    break;
                }
            }
            catch (Exception exception)
            {
                Log.WriteAsync("打开身份证阅读器异常，Error:" + exception.Message);
            }
            Log.WriteAsync("打开身份证阅读器失败");
            return false;
        }

        public void SavePort()
        {
            _option.SerialPortNum = _iPort;
            _option.Save();
        }

        public bool InitCVRReader(int pPort)
        {
            try
            {
                bool flag = false;
                Log.WriteAsync(string.Format("初始化身份证阅读器，串口参数{0}", pPort));
                _iPort = pPort;
                if (_iPort > 0)
                {
                    if(1 == TermbDll_100A.CVR_InitComm(_iPort))
                    {
                        Log.WriteAsync(string.Format("打开身份证阅读器成功，串口{0}", _iPort));
                        flag = true;
                    }                                   
                }
                else
                {
                    flag = this.InitCVRReader();
                }
                if(!flag)
                {
                    Log.WriteAsync("打开身份证阅读器失败");
                }
                _bExited = false;
                _bInited = flag;
                return flag;
            }
            catch (Exception exception)
            {
                Log.WriteAsync("打开身份证阅读器异常，Error:" + exception.Message);
            }
            Log.WriteAsync("打开身份证阅读器失败");
            return false;
        }

        private void LoadConfig()
        {
            if (!File.Exists(_option.ConfigFilePath))
            {
                _option.Save();
            }
            _option.Load();
            this.TimeoutMillisecond = _option.TimeoutSecond * 1000;
        }

        /// <summary>
        /// 执行单次读取身份证操作
        /// </summary>
        /// <returns></returns>
        public bool Read(string inParams, out string outParams)
        {
            outParams = "";
            _error = "";
            if (!_bInited)
            {
                _error = "阅读器未初始化.";
                return false;
            }
            bool readSuccess = false;
            _error = "";
            try
            {
                IdCardInfo cardInfo = null;
                readSuccess = ReadCard(out cardInfo);
                if (readSuccess)
                {
                    outParams = ConvertToJsonString(cardInfo);
                }  
                else
                {
                    outParams = ErrorMessage;
                }
                return readSuccess;
            }
            catch (Exception ex)
            {
                _error = string.Format("读取身份证信息发生了异常.\n异常详情:{0}", ex.ToString());
                Log.WriteExceptionAsync(_error);
                return false;
            }
        }

        private string ConvertToJsonString(IdCardInfo cardInfo)
        {
            IDCardAll idCard = new IDCardAll();
            idCard.number = cardInfo.IdCardCode;
            idCard.address = cardInfo.Address;
            idCard.birthday = cardInfo.Birthday;
            idCard.name = cardInfo.IdCardName;

            idCard.people = cardInfo.Nation;
            idCard.sex = cardInfo.Sex;
            idCard.validtermOfStart = cardInfo.IssueDate;
            idCard.validtermOfEnd = cardInfo.ExpiryDate;
            idCard.HeadImage = cardInfo.Photo;
            return JsonConvert.SerializeObject(idCard);
        }

        private string GetCardInfoString(ref IdCardInfo cardInfo)
        {
            JObject outParam = new JObject();
            outParam.Add("ZJHM", cardInfo.IdCardCode);
            outParam.Add("XM", cardInfo.IdCardName);
            outParam.Add("XB", cardInfo.Sex);
            outParam.Add("MZ", cardInfo.Nation);
            outParam.Add("DZ", cardInfo.Address);
            outParam.Add("CSRQ", cardInfo.Birthday);
            outParam.Add("QFDW", cardInfo.Department);        
            outParam.Add("QFSJ", cardInfo.IssueDate);
            outParam.Add("SXSJ", cardInfo.ExpiryDate);
            outParam.Add("ZP", cardInfo.Photo);
            return outParam.ToString();
        }

        public override void Init(string inParam, out string outParam)
        {
            outParam = "";
            if (_bInited)
            {
                return;
            }
            if (InitCVRReader(_option.SerialPortNum))
            {
                _bInited = true;
                return;
            }
            if(InitCVRReader())
            {
                _bInited = true;
                return;
            }
            _error = string.Format("阅读器初始化失败。\n");
            Log.WriteAsync(_error);
        }

        public override bool DoAction(string param, out string outParam)
        {
            return Read(param, out outParam);
        }

        public override void Start(string param, out string outParam)
        {
            outParam = null;
            poll = new Polling(Read, param);
            poll.TimeoutMilliSecond = TimeoutMillisecond;
            poll.ScanInterval = _option.ScanInterval;
            poll.DoFailed += this.OnDoFailed;
            poll.Timeout += this.OnDoTimeout;
            poll.Start(OnWorkingCompleted);
        }

        public override void Stop(string param, out string outParam)
        {
            outParam = null;
            if (poll != null)
            {
                poll.Stop();
                poll.Dispose();
                poll = null;
            }
        }

        public override void Exit(string inParams, out string outParam)
        {
            outParam = "";
            try
            {
                if(CloseCVRReader())
                {
                
                    DeleteZP();
                }              
            }
            catch (Exception ex)
            {
                Log.WriteExceptionAsync(ex.ToString());
            }
            finally
            {
                _bInited = false;
            }
        }

        /// <summary>
        /// 清理身份证头像相片
        /// </summary>
        public void DeleteZP()
        {
            try
            {
                if (!File.Exists(strZPPath))
                {
                    File.Delete(strZPPath);
                }
            }
            catch (Exception ex)
            {
                string strLog = string.Format("删除ZP发生了异常: {0}", ex.ToString());
                Log.WriteExceptionAsync(strLog);
            }
        }

        public override void ShowConfigDialog(string inParam)
        {
            FormSetting form = new FormSetting();
            form.ShowDialog();
        }
    }
}

